spring boot 2.0.3+spring cloud熔断器Hystrix | 您所在的位置:网站首页 › 通过maven 打docker 镜像包出错add failed stat varlib › spring boot 2.0.3+spring cloud熔断器Hystrix |
分布式系统中服务与服务之间的依赖错综复杂,一种不可避免的情况就是某些服务会出现故障,导致依赖于他们的其他服务出现远程调度的线程阻塞。某个服务的单个点的请求故障会导致用户的请求处于阻塞状态,最终的结果是整个服务的线程资源消耗殆尽。由于服务的依赖性,会导致依赖于该故障服务的其他服务也处于线程阻塞状态,最终导致这些服务的线程资源消耗殆尽,知道不可用,从而导致整个服务系统不可用,即雪崩效应。为了防止雪崩效应,产生了熔断器模型。 Hystrix是Netflix公司开源的一个项目,提供了熔断器功能,能阻止分布式系统中出现联动故障。Hystrix是通过隔离服务的访问点阻止联动故障的,并提供了故障解决方案,从而提高了整个分布式系统的弹性。 当服务的某个API接口的失败次数在一定时间内小于设定的阈值时,熔断器处于关闭状态,该API接口正常提供服务。当该API接口处理请求的失败次数大于设定的阈值时,hystrix判定该API接口出现了故障,打开熔断器,这时请求该API接口会执行快速失败的逻辑(即fallback回退的逻辑),不执行业务逻辑,请求的线程不会处于阻塞状态。处于打开状态的熔断器,一段时间后会处于半打开状态,并将一定数量的请求执行正常逻辑,剩余的请求会执行快速失败,若执行正常逻辑的请求失败了,则熔断器继续打开,若成功了,则关闭熔断器。这样熔断器就具有了自我修复的能力。 最开始集成的时候,发现springBoot1.5.6 和springBoot2.0.3包不兼容,导致后面一致报错,因为工作环境用的还是srpingBoot1.5.6版本,所以练习的这个是最新版本,Hystrix在1.5版本是要自己加载的,但是2.0.3版本已经包含在spring-cloud-starter-netflix-hystrix 包里面了,我是用maven仓库,工作空间都在一起,后面分离了工作空间和maven仓库,让两个版本的依赖仓库分开 ,果然之后一切顺利,这也是比较坑的地方, 先写三个项目springcloud-eureka-server 服务注册中心 springcloud-euraka-client生产者 euraka-consumer-ribbonAndfeign-hystrix 消费者调用 ,并且ribbon 和 feign负载均衡放在一个项目里 主要是euraka-consumer-ribbonAndfeign-hystrix 项目, 先贴出POM.XML的依赖 4.0.0 com.example.euraka springCloudEurakaConsumer 1.0.0 jar springCloudEurakaConsumer Demo project for Spring Boot org.springframework.boot spring-boot-starter-parent 2.0.3.RELEASE UTF-8 UTF-8 Finchley.RELEASE org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.cloud spring-cloud-starter-openfeign org.springframework.boot spring-boot-starter-test test org.springframework.cloud spring-cloud-starter-netflix-hystrix org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import org.springframework.boot spring-boot-maven-plugin com.spotify docker-maven-plugin 在项目启动类加上@EnableHystrix注解,开启hystrix熔断器功能,当然我这里加的比较多,如果是springBootCloudApplicateion也可以,主要是在超时配置的时候,会有过服务重试的操作,这个操作研究了一段时间,基本上就是超时的策略,会去调用其它服务实例,再次请求服务等,详细介绍在配置文件里 @SpringBootApplication @Configuration @EnableEurekaClient @EnableDiscoveryClient @EnableFeignClients @EnableHystrix public class DemoServerApplication { public static void main(String[] args) { SpringApplication.run(DemoServerApplication.class, args); } /* SpringCloud重试机制配置 首先声明一点,这里的重试并不是报错以后的重试,而是负载均衡客户端发现远程请求实例不可到达后,去重试其他实例。 其实也是Ribbon+RestTemplate的重试机制,因为是SpringCloud默认方式 对于整合了Ribbon的RestTemplate,例如一个RestTemplate添加了@LoadBalanced 注解 */ @LoadBalanced @Bean public RestTemplate restTemplate() { /*HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); httpRequestFactory.setReadTimeout(3000); httpRequestFactory.setConnectTimeout(2000); return new RestTemplate(httpRequestFactory);*/ return new RestTemplate(); } //feign重试机制,feign默认是通过自己包下的Retryer进行重试配置,默认是5次,优先配置文件配置的重试策略 //如果没有配置文件,下面这样设置至少也会重试两次,本实例之外的一次调用 @Bean public Retryer feignRetryer(){ // return new Retryer.Default(100,TimeUnit.SECONDS.toMillis(1),5);//默认是5次 return Retryer.NEVER_RETRY; //feign取消重试 } 然后在CustomerRibbonController里,实现Ribbon+RestTemplate 负载均衡实现 ,其实也比较简单,因为我之前测试别的原因,我写了两个方法 @RestController public class CustomerRibbonController { @Autowired RestTemplate restTemplate; @Autowired RibbonService ribbonService; //这里写了一个service 层来表示业务逻辑,当然与下面worldCustomer的方式调用也是可以的,简洁一些 // hellolmc 方法调用超时之后, 调用fallbackMethod = "hiError" 方法,自动熔断或降级 @GetMapping("/hilmc") public String hellolmc(){ return ribbonService.consumer(); } //此方法可以正常调用,生产者并没有超时 @RequestMapping(value = "/helloCustomer",method = RequestMethod.GET) @HystrixCommand(fallbackMethod="fallback") public String worldCustomer(){ return restTemplate.getForObject("http://springcloud-euraka-client/world", String.class); } public String fallback() { System.out.println("fallbackMethod worldCustomer"); return "fallback Customer"; } } @Service public class RibbonService { @Autowired RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "hiError") public String consumer() { return restTemplate.getForObject("http://springcloud-euraka-client/hello", String.class); } public String hiError() { return "fallbackCall"; } } RibbonService 是因为把业务把控制层分开,第一个方法是这样调用 在consumer()方法上加上@HystrixCommand注解。有了该注解consumer()方法就启用了Hystrix熔断器的功能,fallbackMethod为处理回退(fallback)逻辑的方法为hiError() ,没有异常,直接返回一个字符串,也可以用抛异常的方式执行,这样在日志里可以发现哪个服务出现问题,只需要在 hiError() 里加thrable 等方式,我这里为了简便就没有做,主要是不想处理复杂的逻辑,,这样方便执行快速失败,释放线程资源,项目结构是这样
加上配置文件,因为是ribbon 和 feign放在一起,还有重试策略配置等, server: port: 5080 eureka: client: serviceUrl: defaultZone: http://peer1:5012/eureka/ healthcheck: enabled: true lease: duration: 5 instance: preferIpAddress: true spring: application: name: springCloudEurakaConsumer #使用如下配置开启,即可实现重试:再加Feign下面的ribbon配置,就是 Ribbon+RestTemplate的重试机制 # cloud: # loadbalancer: # retry: # enabled: true #开启hystrix功能 feign: hystrix: enabled: true #logging: # level: # org.exampledriven.eureka.customer.shared.CustomerServiceFeignClient: FULL #lease 租期时间,不定时发送心跳包消息,如果长时间未能更新租期时间,服务就为抛弃该服务实例,注册中心会当成无用服务 # 1,Ribbon+RestTemplate的重试 #对于整合了Ribbon的RestTemplate,例如一个RestTemplate添加了@LoadBalanced 注解 #在此基础上,使用如下配置,即可实现重试: #Feign的重试与Ribbon重试整合后, 只需使用Ribbon的重试配置即可,两种重试配置一样,所以下面配置至少要重试4次 ribbon: # 同一实例最大重试次数,不包括首次调用,配置后本实例至少会执行两次 MaxAutoRetries: 1 # 重试其他实例的最大重试次数,不包括首次所选的server,配置后本实例和其它服务注册实例至少会执行两次 MaxAutoRetriesNextServer: 1 # 是否所有操作都进行重试 OkToRetryOnAllOperations: false 到这里ribbon配置基本完成, 依次启动springcloud-eureka-server 的服务注册,springcloud-euraka-client生产者 euraka-consumer-ribbonAndfeign-hystrix消费消息,在浏览器访问http://localhost:5080/hilmc,会显示如下, 因为我在生产端直接睡眠了9秒,所以触发熔断 再输入正常url http://localhost:5080/helloCustomer 显示正常
在Feign上使用熔断器 下面是feign 包 Feign的起步依赖中已经引入了Hystrix的依赖,只需要在eureka-feign-client工程的配置文件中开启hystrix功能即可,前方配置文件已经给出 EurekaClientFeign 接口, @Component @FeignClient(value = "springcloud-euraka-client",fallback = HiHystrix.class) public interface EurekaClientFeign { /** * 绑定 springcloud-euraka-client 服务的 /hi/ 接口 * * @param name * @return */ @GetMapping(value = "/hi") String sayHiFromClientEureka(@RequestParam(value = "name")String name); @GetMapping(value = "/hi2") String sayHiFromClientEureka2(@RequestParam(value = "name")String name); } HiHystrix 类必须实现EurekaClientFeign接口,才能触发熔断器的fallback @Component public class HiHystrix implements EurekaClientFeign { @Override public String sayHiFromClientEureka(String name) { return "hi,"+name+",sorry.error!"; } @Override public String sayHiFromClientEureka2(String name) { return "hi2,"+name+",sorry.error! Hi2"; } } CustomerFeignController 类 @RestController public class CustomerFeignController { @Autowired EurekaClientFeign eurekaclient; //超时调用fallback 的方法,如果禁止重试,也会调用两次,如果配置文件有调用其它实例,至少会执行3次以上 //所以在写接口的时候,需要对接口增加幂等性 @GetMapping("/hi") public String sayHi(@RequestParam(defaultValue = "cralor",required = false)String name){ return eurekaclient.sayHiFromClientEureka(name); } //正常执行调用 @GetMapping("/hi2") public String sayHi2(@RequestParam(defaultValue = "lmc",required = false)String name){ return eurekaclient.sayHiFromClientEureka2(name); } @Autowired private GreetingClient greetingClient; @RequestMapping("/get-greeting") public String greeting(Model model) { Map parpm= new HashMap(); parpm.put("name", "lmc"); parpm.put("test", "demo"); String message = greetingClient.greeting(parpm.toString()); //以字符串方式传参数 return message+":传参数"; } 浏览器访问输入http://localhost:5080//hi2 正常调用 浏览器访问输入http://localhost:5080//hi 这个方法在springcloud-euraka-client 项目里启动睡眠6秒超时
都 能触发熔断降级处理, 说明是可行, 还要注意的是 feign 重试机制,就是在超时或者异常的情况下,会不断去重试调用,feign默认重试次数是5次,100ms一次 这最前面的配置文件最后参数有说明 ,就是除了本身实例,本身服务,再去调用其它实例和服务,在集群的环境下配置这种策略最好,如果碰上数据量过大请求过去超时,但是生产者那方会如果没有限制超时就会继续执行,这个时间再去重试请求其实是非常危险的,一条数据会碰上执行两次以上,get的数据可能影响不大,如果是post写数据就要考虑接口的幂等性 使用Hystrix Dashboard监控熔断器的状态 这个跟eurak服务注册类型的步骤,有时间再弄会,集群监控所有熔断器的状态和运用情况等 githut项目地址 https://github.com/lmchuyang/huyang 如有理解 错的,希望大家能指正交流 参考资料 https://www.cnblogs.com/cralor/p/9230728.html 参考资料 https://www.jb51.net/article/129336.htm |
CopyRight 2018-2019 实验室设备网 版权所有 |